package com.ecoolex.chinadutyfree.retailer.core.manager;

import java.time.Instant;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ecoolex.chinadutyfree.retailer.core.dao.GoodsCategoryDAO;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsCategory;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsCategory.Column;
import com.ecoolex.chinadutyfree.retailer.entity.GoodsCategoryExample;
import com.ecoolex.chinadutyfree.retailer.enums.DirectMailGoodsStatus;
import com.ecoolex.chinadutyfree.retailer.pojo.GoodsCategoryTopChildDO;
import com.ecoolex.chinadutyfree.retailer.pojo.QueryGoodsCategoryDTO;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;


@Service
public class GoodsCategoryManager {

	@Autowired
	private GoodsCategoryDAO dao;

	private GoodsCategory verify(GoodsCategory record) {
		BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "名称不能为空");
		if (Check.isNullOrLtOne(record.getParentCategoryId())) {
			return null;
		} else {
			GoodsCategory parent = getById(record.getParentCategoryId());
			BizAssert.isTrue(Check.notNull(parent), ResultCode.BIZ.build(1), "父级分类不存在");
			return parent;
		}
	}

	public GoodsCategory add(GoodsCategory record, String createUser) {
		GoodsCategory parent = verify(record);
		if (Check.isNull(parent)) {
			record.setParentCategoryId(0);
			record.setLevel(1);
		} else {
			record.setParentCategoryId(parent.getCategoryId());
			record.setLevel(parent.getLevel() + 1);
		}

		record.setIsShow(true);
		record.setDeleted(GoodsCategory.NOT_DELETED);
		record.setCreateUser(createUser);
		record.setCreateTime(Date.from(Instant.now()));
		record.setUpdateUser(createUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.insert(record);
		return record;
	}

	public GoodsCategory update(GoodsCategory record, String updateUser) {
		GoodsCategory parent = verify(record);
		if (Check.isNull(parent)) {
			record.setParentCategoryId(0);
			record.setLevel(1);
		} else {
			record.setParentCategoryId(parent.getCategoryId());
			record.setLevel(parent.getLevel() + 1);
		}

		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record,
			Column.excludes(Column.isShow, Column.deleted, Column.createUser, Column.createTime));
		return record;
	}

	public void delete(GoodsCategory record, String updateUser) {
		GoodsCategoryExample example = new GoodsCategoryExample();
		example.createCriteria().andParentCategoryIdEqualTo(record.getCategoryId()).andDeletedEqualTo(
			GoodsCategory.NOT_DELETED);
		long childCount = dao.countByExample(example);
		BizAssert.isTrue(childCount < 1, ResultCode.BIZ.build(1), "存在{}个子分类,无法删除", childCount);

		record.setDeleted(GoodsCategory.IS_DELETED);
		record.setUpdateUser(updateUser);
		record.setUpdateTime(Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.deleted, Column.updateUser, Column.updateTime);
	}

	public GoodsCategory getById(Integer categoryId) {
		return dao.selectByPrimaryKeyWithLogicalDelete(categoryId, GoodsCategory.NOT_DELETED);
	}

	public List<GoodsCategory> queryByParentId(Integer parentCategoryId, Boolean isShow) {
		GoodsCategoryExample example = new GoodsCategoryExample();
		GoodsCategoryExample.Criteria criteria = example.createCriteria();
		criteria.andParentCategoryIdEqualTo(parentCategoryId);

		if (Check.notNull(isShow)) {
			criteria.andIsShowEqualTo(isShow);
		}

		criteria.andDeletedEqualTo(GoodsCategory.NOT_DELETED);
		example.orderBy(Column.sorting.asc());

		return dao.selectByExample(example);
	}

	public Pagination<GoodsCategory> query(QueryGoodsCategoryDTO query, Sorting[] sorts, Page page) {
		GoodsCategoryExample example = new GoodsCategoryExample();
		GoodsCategoryExample.Criteria criteria = example.createCriteria();

		if (Check.notNull(query.getParentCategoryId())) {
			criteria.andParentCategoryIdEqualTo(query.getParentCategoryId());
		}
		if (Check.notNull(query.getLevel())) {
			criteria.andLevelEqualTo(query.getLevel());
		}
		if (Check.notNullOrTrimEmpty(query.getName())) {
			criteria.andNameLike('%' + query.getName()
				+ '%');
		}
		if (Check.notNull(query.getIsShow())) {
			criteria.andIsShowEqualTo(query.getIsShow());
		}

		criteria.andDeletedEqualTo(GoodsCategory.NOT_DELETED);

		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());

		return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
	}

	public GoodsCategory show(GoodsCategory record, String updateUser) {
		record.setIsShow(true);
		record.setUpdateUser(updateUser);
		record.setUpdateTime(java.sql.Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.isShow, Column.updateUser, Column.updateTime);
		return record;
	}

	public GoodsCategory hide(GoodsCategory record, String updateUser) {
		record.setIsShow(false);
		record.setUpdateUser(updateUser);
		record.setUpdateTime(java.sql.Date.from(Instant.now()));
		dao.updateByPrimaryKeySelective(record, Column.isShow, Column.updateUser, Column.updateTime);
		return record;
	}

	public Pagination<GoodsCategory> queryForH5(Integer level, Integer parentCategoryId, Sorting[] sorts, Page page) {
		GoodsCategoryExample example = new GoodsCategoryExample();
		GoodsCategoryExample.Criteria criteria = example.createCriteria();

		if (Check.notNull(parentCategoryId)) {
			criteria.andParentCategoryIdEqualTo(parentCategoryId);
		}
		criteria.andLevelEqualTo(level);
		criteria.andIsShowEqualTo(true);
		criteria.andDeletedEqualTo(GoodsCategory.NOT_DELETED);

		example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
		example.setOffset(page.getFirstIndex());
		example.setRows(page.getPageSize());

		return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
	}

	public List<GoodsCategoryTopChildDO> queryCategoryTopChild(Integer minNumber, Integer size) {
		return dao.queryCategoryTopChild(DirectMailGoodsStatus.RELEASE.real(), minNumber, size);
	}
}